package com.ymt.fmd.platform.web.rest;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

import com.ymt.fmd.appboot.prop.FmdProperties;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ymt.fmd.platform.dao.mysql.CustomSQLDao;
import com.ymt.fmd.platform.dao.mysql.PDataSMapper;
import com.ymt.fmd.platform.model.PBizDocS;
import com.ymt.fmd.platform.model.PDataS;
import com.ymt.fmd.platform.service.BoDataService;
import com.ymt.fmd.platform.service.FmdService;
import com.ymt.fmd.platform.service.ImportExportService;
import com.ymt.fmd.platform.service.MetadataService;
import com.ymt.fmd.util.Const;
import com.ymt.fmd.util.ExcelUtil;


@SuppressWarnings({ "rawtypes", "unused", "unchecked" })
@Component
@EnableConfigurationProperties(value = {FmdProperties.class})
@Path("/excel")
public class ImportExportResource {

	private static Logger logger = Logger.getLogger(ImportExportResource.class.getName());

	@Autowired
	private FmdProperties fmdProperties;
	
	@Autowired
	private ImportExportService ies;

	@Autowired
	private CustomSQLDao csDao;

	@Autowired
	private BoDataService bds;

	@Autowired
	private FmdService fService;
	
	@Autowired
	private MetadataService mdService;

	@Context
	private HttpServletRequest request;

	@Autowired
	private PDataSMapper dsDao;
	
	@Autowired
    private MongoTemplate mt;

	/**
	 * <导出> <br/>
	 * <功能详细描述>
	 */
	//@GET
	@Path("export")
	@Produces(MediaType.APPLICATION_JSON)
	public String export2Excel(@Context HttpServletRequest req,
			@Context HttpServletResponse resp,
			@FormParam("dictMaps")String dictMaps) throws Exception {

		Map<String, String> userDetail = (Map<String, String>) SecurityContextHolder.getContext().getAuthentication().getDetails();

		boolean JSONDATA_ENABLED = Boolean.parseBoolean(fmdProperties.getJsondataEnabled());
		boolean MONGODATA_BIZ = Boolean.parseBoolean(fmdProperties.getMongodataBiz());
		String DB_RESOLVER = fmdProperties.getBoDbresolver();

		String tenantId = userDetail.get(Const.TENANT_ID);
		String appId = req.getParameter("appId");
		String isBiz = req.getParameter("ib");
		logger.finer("export2Excel tenantId="+tenantId);
		logger.finer("export2Excel appId="+appId);
		logger.finer("export2Excel isBiz="+isBiz);
		logger.finer("dictMaps="+dictMaps);
		JSONObject map = null;
		if (dictMaps!=null && dictMaps.length()>0) {
			map = JSONObject.parseObject(dictMaps);
		}
		List<String> list = new ArrayList<String>();
		List<String> tlist = new ArrayList<String>();
		List<Integer> eList = new ArrayList<Integer>();
		List<List<String>> data = new ArrayList<List<String>>();
		List<String> thlist = new ArrayList<String>();
		List<String> enulist = new ArrayList<String>();
		String[] enu = new String[]{};
		String formId = req.getParameter("formId");
		String versionId = req.getParameter("versionId");
		String gid = req.getParameter("gid");
		String tsId = req.getParameter("tsId");
		String rtn = fService.getVersion(formId, versionId);
		JSONObject res = JSONObject.parseObject(rtn);
		JSONObject jo = res.getJSONObject("version").getJSONObject("formdata").getJSONObject("propconf").getJSONObject(gid);
		String model = jo.getString("model");
		JSONArray ja = jo.getJSONArray("gridsetting");
		for (int i = 0; i < ja.size(); i++) {
			JSONObject ja1 = (JSONObject) ja.get(i);
			String id = (String) ja1.get("id");
			String zhName = (String) ja1.get("zh");
			if(ja1.get("hidden").equals("0")){	//不是隐藏列
				list.add(id);
				tlist.add(zhName);
//				map.put(id, zhName);
			}
			if(ja1.get("editortype").equals("coro")){	//下拉框
				eList.add(i);
			}
			/*if(ja1.get("meta").equals("dataprovider-dict") && ja1.get("editortype").equals("coro")){
				String metaType = (String) ja1.getJSONObject("metasource").get("type");
				JSONObject jsObject = new JSONObject();
				JSONArray jsArray = new JSONArray();
				jsObject.put("target", "BPM");
				jsObject.put("type", metaType);
				jsArray.add(jsObject);
				String tenantId0 = getTenantId();
				String metaRtn = mdService.getEnumerations(tenantId0,"zh",jsArray.toString());
				JSONObject jsStr = JSONObject.parseObject(metaRtn);
				Object typeArr = jsStr.get(metaType);
				JSONArray typeVals = null;
				if (typeArr instanceof JSONArray) {
					typeVals = (JSONArray)typeArr;
				} else {
					typeVals = JSONArray.parseArray(typeArr.toString());
				}
				List enuList = new ArrayList();
				for(int k = 0;k < typeVals.size(); k++){
					JSONArray jay = (JSONArray) typeVals.get(k);
					enuList.add(jay.get(0)+ "-" +jay.get(1));
				}
				map.put(i, enuList);
			}*/
		}		
		
		//获取导出表列		
		String[] cols = new String[] {};
		cols = (String[]) list.toArray(cols);
		String head = StringUtils.join(cols, ",");
		//获取表列描述
		String[] tcols = new String[]{};
		tcols = (String[])tlist.toArray(tcols);
		long time = System.currentTimeMillis();
		ExcelUtil export = new ExcelUtil();
		OutputStream out = null;
		// 获取当前服务器的时间：年月日时分秒
		String ddate = new SimpleDateFormat("yyyyMMddHHmmss").format(Calendar.getInstance().getTime());
		String filename = "export" + ddate + ".xls";

		try {
			//创建表头
//			export.createTableHeader(tcols);
			// 解决在IE中文件名乱码
			filename = URLEncoder.encode(filename, "utf-8");
			// 弹窗提示保存路径,解决导出后文件名乱码问题
			resp.setContentType("application/ms-excel");
			ExcelUtil.setFileDownloadHeader(req, resp, filename);
			out = resp.getOutputStream();
			//查询导出数据
			if ("1".equals(isBiz) && MONGODATA_BIZ) {
				Query query = new Query(Criteria.where("sharedId").is(tsId).and("model").is(model.toUpperCase())).with(new Sort(new Order(Sort.Direction.ASC, "itemNo")));
				List<PBizDocS> rs = mt.find(query, PBizDocS.class, "C1_"+
						(tenantId!=null && tenantId.length()>0 ? tenantId : '0')+"_"+
						(appId!=null && appId.length()>0 ? appId : '0')+"_"+
						model.toUpperCase());
				if(rs.size()>0){
					for (PBizDocS doc : rs) {
						List tmpList = new ArrayList<String>();
						JSONObject map1 = doc.getData();
						for(int k =0;k<list.size();k++){
							tmpList.add(map1.get(list.get(k)));
						}
						data.add(tmpList);
					}
				}else{
					data = null;
				}
			} else if (JSONDATA_ENABLED) {
				PDataS key = new PDataS();
				if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
					key.setTenantId(Integer.parseInt(tenantId));
				}
				key.setPiEid(tsId);
				key.setModel(model);
				List<PDataS> rs = dsDao.selectByObj(key);
				if(rs.size()>0){
					for (int i = 0; i < rs.size(); i++) {
						List tmpList = new ArrayList<String>();
						JSONObject map1 = JSONObject.parseObject(rs.get(i).getBizData());
						for(int k =0;k<list.size();k++){
							tmpList.add(map1.get(list.get(k)));
						}
		 
						data.add(tmpList);
					}
				}else{
					data = null;
				}
			} else {
				String sql = "select " + head + " from " + model + " where ts_id='" + tsId + "'";
				List<Map<String, ?>> rs = csDao.selectAll(sql);
				if(rs.size()>0){
					for (int i = 0; i < rs.size(); i++) {
						List<String> rlist = new ArrayList<String>();
						List tmpList = new ArrayList<String>();
						LinkedHashMap lhm = new LinkedHashMap();
						Map<String, ?> map1 = rs.get(i);
						for(int k =0;k<list.size();k++){
							tmpList.add(rs.get(i).get(list.get(k)));
						}
		 
						data.add(tmpList);
					}
				}else{
					data = null;
				}
			}
			
//			export.createTableRow(data);
//			export.expord(out);
			
			export.exportAll(tcols,eList,map,data,out);
			
			logger.finer("成功导出数据到" + filename + ",共用时" + (System.currentTimeMillis() - time) / 1000.0 + "秒");
			return "{\"result\":true}";
		} catch (Exception e) {
			e.printStackTrace();
			return "{\"result\":false}";
		}finally{
			out.flush();
			out.close();
		}

	}

	/**
	 * <导入功能> <br/>
	 * <功能详细描述>
	 * @return
	 * @throws Exception
	 */
	@POST
	@Path("import")
	@Produces("text/html;charset=UTF-8")
	// 导入先上传至服务器临时目录，然后再导入数据库
	public String importExcel(@Context HttpServletRequest req,
			@Context HttpServletResponse resp) throws Exception {

		boolean JSONDATA_ENABLED = Boolean.parseBoolean(fmdProperties.getJsondataEnabled());
		boolean MONGODATA_BIZ = Boolean.parseBoolean(fmdProperties.getMongodataBiz());
		String DB_RESOLVER = fmdProperties.getBoDbresolver();

		Map<String, Object> map = new HashMap<String, Object>();
		List<String> list = new ArrayList<String>();
		List<String> tlist = new ArrayList<String>();
		List<String> typeList = new ArrayList<String>();
		List<String> etList = new ArrayList<String>();
		List tmpList = new ArrayList<String>();
		List<String> thlist = new ArrayList<String>();
		List<String> typeCList = new ArrayList<String>();
		List<List<String>> data = new ArrayList<List<String>>();
		List<String> sList = new ArrayList<String>();

		Map<String, Object> rMap = new HashMap<String, Object>();
		List dList = new ArrayList<String>();

		JSONArray dja = new JSONArray();
		JSONObject djo = new JSONObject();

		String columns = null;
		String formId = req.getParameter("formId");
		String versionId = req.getParameter("versionId");
		String gid = req.getParameter("gid");
		String tsId = req.getParameter("tsId");
		String rtn = fService.getVersion(formId, versionId);
		JSONObject res = JSONObject.parseObject(rtn);
		JSONObject jo = res.getJSONObject("version").getJSONObject("formdata")
				.getJSONObject("propconf").getJSONObject(gid);
		String model = jo.getString("model");
		JSONArray ja = jo.getJSONArray("gridsetting");
		for (int i = 0; i < ja.size(); i++) {
			JSONObject ja1 = (JSONObject) ja.get(i);
			String id = (String) ja1.get("id");
			String zhName = (String) ja1.get("zh");
			String type = (String) ja1.get("type");
			String editortype = (String) ja1.get("editortype");
			String hidden = (String) ja1.get("hidden"); // 是否隐藏
			list.add(id);
			if ("1".equals(hidden)) {
				tlist.add("");
			} else {
				tlist.add(zhName);
				etList.add(editortype);
				typeList.add(type);
			}
			map.put(zhName, id);
		}
		logger.finer("etList="+etList);
		String[] cols = new String[] {};
		cols = (String[]) list.toArray(cols);
		String head = StringUtils.join(cols, ",");

		String[] tcols = new String[] {};
		tcols = (String[]) tlist.toArray(tcols);

		String[] typecols = new String[] {};
		typecols = (String[]) typeList.toArray(typecols);

		String[] typeColoumn = new String[] {};

		Map<String, Object> umap = upload(req, resp);
		if (umap.get("flag").equals(true)) {
			resp.setContentType("text/html;charset=utf-8;");
			// 设置接收的编码格式
			req.setCharacterEncoding("UTF-8");
			String filePath = (String) umap.get("filePath");
			String fileType = (String) umap.get("fileType");
			FileInputStream is = new FileInputStream(new File(filePath));
			if ("xls".equals(fileType)) {
				data = ExcelUtil.importFromExcel(is, model, tlist, etList);
				logger.finer("importExcel data=" + data);
			} else {
				data = ExcelUtil.importEx(is, tlist, etList);
				logger.finer("importExcel data=" + data);
			}
			
			String maxsql = "select max(item_no_) AS MAXNO from "
					+ model + " where ts_id='" + tsId + "'";
			List<Map<String, ?>> lsList = csDao.select(maxsql);
			int maxItemNo = 1;
			if (lsList != null && lsList.size() > 0
					&& lsList.get(0) != null) {
				Object ob = lsList.get(0).get("MAXNO");
				maxItemNo = Integer.parseInt(ob.toString());
			}

			for (int i = 0; i < data.size(); i++) {
				// 获取表头
				if (i == 0) {
					sList = data.get(i);
					thlist.add(0, "TS_ID");
					thlist.add(1, "ITEM_NO_");
					for (int k = 0; k < sList.size(); k++) {
						String ss = sList.get(k);
						ss = ss.replaceAll("\"", "");
						thlist.add((String) map.get(ss));
						typeCList.add((String) map.get(ss));
					}
					;
					String[] val = new String[] {};
					val = (String[]) thlist.toArray(val);
					String[] varType = new String[] {};
					varType = (String[]) typeCList.toArray(varType);
					typeColoumn = (String[]) typeCList.toArray(varType);
					columns = StringUtils.join(val, ",");
				} else {
					List<Object> vList = new ArrayList<Object>();
					int item_no = maxItemNo + 1;
					vList.add(0, 0); // _SEL
					vList.add(1, 1); // _CHANGED
					vList.add(2, i); // _NO
					vList.add(String.valueOf(item_no)); // //ITEM_NO_
					// vList.add(0, "\'" + tsId + "\'");
					// vList.add(1, "\'" + String.valueOf(item_no) + "\'");
					String[] hval = new String[] {};
					hval = (String[]) data.get(i).toArray(hval);

					// for(int s=0;s<typeColoumn.length;s++){
					// if("datetime".equals(typecols[s])){
					// if(StringUtils.isNotEmpty(hval[s])){
					// // hval[s] = "to_date("+hval[s]+",'yyyy-MM-dd')";
					// hval[s] = hval[s];
					// }else{
					// hval[s] = null;
					// }
					// }else{
					// if("\"\"".equals(hval[s])){
					// hval[s] = "null";
					// }
					// }
					// }
					String hh = StringUtils.join(hval, ",");
					String hhn = hh.replaceAll("\"", "");

					vList.addAll(Arrays.asList(hhn.split(",")));
					//vList.addAll(data.get(i));
					
					// vList.add(hh.replaceAll("\"", "\'"));
					// String[] val = new String[] {};
					// val = (String[]) vList.toArray(val);
					// String resVal = StringUtils.join(val, ",");

					// dList.add(resVal);
					// rMap.put("id", i+1);
					// rMap.put("data", dList);

					// JSONArray jsonArray = new JSONArray();
					// jsonArray.add(resVal);

					JSONObject jsonObject = new JSONObject();
					jsonObject.put("id", i);
					jsonObject.put("data", vList);
					dja.add(jsonObject);
					djo.put("rows", dja);

					// String sql = "insert into " + model + "(" + columns +
					// ") values (" + resVal + ")";
					// csDao.insert(sql);
				}
			}
			djo.put("total_count", data.size() - 1);
			djo.put("pos", 0);

			File tfile = new File(filePath);
			// 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
			if (tfile.exists() && tfile.isFile()) {
				if (tfile.delete()) {
					logger.finer("删除单个文件成功！");
				} else {
					logger.finer("删除单个文件失败！");
				}
			} else {
				logger.finer("删除单个文件失败：文件不存在！");
			}
			logger.finer(djo.toString());
			return djo.toString();
			// return "{\"result\":true}";
		} else {
			return "{\"result\":false}";
		}
	}

	@POST
	@Path("parseExcelOnServer")
	@Produces(MediaType.APPLICATION_JSON)
	public String parseExcelOnServer(@Context HttpServletRequest req,
			@Context HttpServletResponse resp) {
		logger.finer("parseExcelOnServer start");
		resp.setCharacterEncoding(Const.ENCODING);
		String rtn = ies.parseExcelOnServer(req);
		logger.finer("parseExcelOnServer returns:" + rtn);
		return rtn;
	}
	
	//得到上传文件的保存目录，将上传的文件存放于WEB-INF目录下，不允许外界直接访问，保证上传文件的安全
		private Map<String, Object> upload(HttpServletRequest request, HttpServletResponse response) {
			Map<String, String> userDetail = (Map<String, String>) SecurityContextHolder.getContext().getAuthentication().getDetails();
			String tmpDir = fmdProperties.getImpexpTmpDir();	//临时文件位置
			String uploadPath = request.getServletContext().getRealPath("/") + tmpDir; // 上传文件的目录
			String tempPath = uploadPath + "\\buffer\\"; // 临时文件目录
			Map<String, Object> map = new HashMap<String, Object>();
			File uploadFile = new File(uploadPath);
			if (!uploadFile.exists()) {
				uploadFile.mkdirs();
			}
			File tempPathFile = new File(tempPath);
			if (!tempPathFile.exists()) {
				tempPathFile.mkdirs();
			}
			try {
				// 创建文件项工厂对象
				DiskFileItemFactory factory = new DiskFileItemFactory();
				// 设置临时保存解析出的数据大小
				factory.setSizeThreshold(4096); // 设置缓冲区大小，这里是4kb,-1无上限
				factory.setRepository(tempPathFile);// 设置缓冲区目录
				// 创建文件上传控制器(Apache组建文件上传的核心类 )
				ServletFileUpload upload = new ServletFileUpload(factory);
				// 解决上传文件名的中文乱码
				upload.setHeaderEncoding("UTF-8");
				// 设置最大文件尺寸,这里设500MB
				upload.setSizeMax(500 * 1024 * 1024);
				List<FileItem> items = upload.parseRequest(request);// 得到所有的文件
				Iterator<FileItem> i = items.iterator();
				while (i.hasNext()) {
					FileItem fi = (FileItem) i.next();
					String fileNameFull = fi.getName();
					if (fileNameFull != null) {
						// 获取文件名
						String fileName = fileNameFull.substring(0,fileNameFull.lastIndexOf("."));
						logger.finer(fileName);
						// 获取文件扩展名
						String extName = fileNameFull.substring(fileNameFull.lastIndexOf("."));
						String filType = fileNameFull.substring(fileNameFull.lastIndexOf(".") + 1,fileNameFull.length());
						logger.finer(extName);
						logger.finer(filType);
						// 生成新的UUID名
						String newName = UUID.randomUUID().toString();
						logger.finer(newName + extName);
						// 获取文件路径
						String filePath = uploadPath + newName + extName;
						logger.finer(filePath);
						File savedFile = new File(uploadPath, newName + extName);
						map.put("filePath", filePath);
						map.put("fileType", filType);
						fi.write(savedFile);
					}
					fi.getOutputStream().close();
				}
				map.put("flag", true);
			} catch (Exception e) {
				// 可以跳转出错页面
				map.put("flag", false);
				e.printStackTrace();
			}
			return map;
		}
	
	/**
	 * 由于tenantId存在于主键中，所以如果不存在则给一个默认值0
	 * @return
	 */
	private String getTenantId() {
		Map<String, String> userDetail = (Map<String, String>) SecurityContextHolder.getContext().getAuthentication().getDetails();
		String tenantId = userDetail.get(Const.TENANT_ID);
		if (tenantId==null) {
			return "0";
		}
		return tenantId;
	}
}
